;   This program is free software: you can redistribute it and/or modify
;   it under the terms of the GNU General Public License as published by
;   the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.
;
;   This program is distributed in the hope that it will be useful,
;   but WITHOUT ANY WARRANTY; without even the implied warranty of
;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;   GNU General Public License for more details.
;
;   You should have received a copy of the GNU General Public License
;   along with this program.  If not, see <http://www.gnu.org/licenses/>.
;
;上一个程式dir_a_file.asm是印出指定档案的资料，这个增加一些功能，
;首先读入参数，例如键入的参数是 A*.*，程式就以A*.*作为搜寻的目标，
;若没有输入参数，则以*.*（万用字元）作为搜寻的目标。
;
;同样利用int21h / Ah=4Eh做第一次搜寻，印出，再利用int21h / Ah=4Fh
;做后续搜寻，直到传回cf=1为止，表示当前文件夹再也找不到档案了，
;最后印出全部显示档案和文件夹的总数。
;
;程式执行时，可按ESC离开，按空白键暂停。
;这程式实现了DOS的DIR部份功能，没有实现的是多层文件夹和排序等等，
;留待有空再说了。
;
data segment

buffer          db      100H dup(?)
filename        db      '*.*',0

name_list       db      14 dup (' ')
file_data       db      '       '
size_end        db      ' '
                db      ' '
file_month      dw      0
                db      '-'
file_date       dw      0
                db      '-'
file_year       dw      0
                dw      0
                db      ' '
file_hour       dw      0
                db      ':'
file_min        dw      0
dir_or_space    db      '<DIR>',0dh,0ah,'$'
dir_str         db      '<DIR>'
dir_L           equ     $ - offset dir_str
space_str       db      dir_L dup (20h)
zero_sign       db      '           0'
zero_L          equ     $ - offset zero_sign
dir_count       dw      0
file_count      dw      0
directory_list  db      '0',4 dup (' '),'File(s), '
dir_count_str   db      '0',4 dup (' '),'Dir(s)','$'
data ends

stack segment
                db      50 dup(?)
stack ends

code segment
assume cs:code,ds:data,ss:stack
p proc far
                mov     ax,data
                mov     ds,ax
                cld
                mov     dx,offset buffer
                mov     ah,1ah
                int     21h
                MOV     SI,82H
                xor     cx,cx
                mov     cl,es:[si-2] ;get length
                mov     dx,offset filename
                mov     bx,cx
                mov     byte ptr es:[si+bx-1],0 ;clear 0dh
                jcxz    pr_00
                mov     dx,si
                push    es
                pop     ds
pr_00:          mov     cx,0ffffh
                mov     ah,4eh
                int     21h
                mov     ax,data
                mov     ds,ax
                mov     es,ax
                jnc     pr_0
    	jmp	quit

pr_0:           mov     di,offset name_list
                mov     si,offset buffer
                add     si,1eh
                mov     cx,15
                push    si

pr_1:           lodsb
                or      al,al
                jz      pr_2
                stosb
                loop    pr_1

pr_2:           mov     al,' '
		rep	stosb
		mov 	si,offset buffer

		mov	ax,ds:[si+1ah]                   ;size lo
		mov	dx,ds:[si+1ch]                   ;size hi
		or	dx,dx
		jnz	pr_40
		or	ax,ax
		jnz	pr_40

pr_30:		mov	bx,offset zero_sign             ;size = 0

pr_35:		push	si
		push	di
		mov	si,bx
		mov	di,offset name_list + zero_L
		mov	cx,zero_L
		rep	movsb
		pop	di
		pop	si
		jmp	short pr_50

pr_40:		mov	di,offset size_end
		mov	cx,10
		call	store_dec

pr_50:		mov	dx,word ptr [si+18h]
		mov	ax,dx
		and	al,00011111b
		aam
		or	ax,3030h
		xchg	ah,al
		mov	file_date,ax
		mov	ax,dx
		mov	cx,5
		shr	ax,cl
		and	al,00001111b            ;get month
		aam
		or	ax,3030h
		xchg	ah,al
		mov	file_month,ax

		mov	ax,dx
		mov	cx,9
		shr	ax,cl
		add	ax,1980		;first Year
		
		push	di
		push	si
		push	bx
		push	dx
		mov	di,offset file_year
		mov	si,10
		mov	bl,30h
		xor	cx,cx
pr_55:		xor	dx,dx
		div	si
		or	dl,bl
		push	dx
		inc	cx
		or	ax,ax
		jnz	pr_55

pr_60:		pop	ax
		stosb
		loop	pr_60
		;
		pop	dx
		pop	bx
		pop	si
		pop	di
		;
                mov     dx,word ptr [si+16h]     ;hour ,minute, second
		mov	ax,dx                   ;xxxxx xxxxxx xxxxx
		mov	cx,11
		shr	ax,cl
		and	al,00011111b

		aam
		or	ax,3030h
		xchg	ah,al
		mov	file_hour,ax
		mov	ax,dx
		mov	cx,5
		shr	ax,cl
		and	al,00111111b
		aam
		or	ax,3030h
		xchg	ah,al
		mov	file_min,ax
		
                cmp     byte ptr [si+15h],10h     ;directory ?
                jz      pr_70
                inc     file_count
                mov     si,offset space_str
                jmp     short pr_71
pr_70:          inc     dir_count
                mov     si,offset dir_str
pr_71:          mov     di,offset dir_or_space
                mov     cx,dir_L
                rep     movsb
                ;
                mov     dx,offset name_list
		mov	ah,9
		int	21h
                ;
                mov     ah,1
                int     16h
                jz      pr_80
                mov     ah,0
                int     16h
                cmp     al,1bh
                jz      quit
                cmp     al,20h
                jnz     pr_80
                mov     ah,0
                int     16h

pr_80:          mov     ah,4fh
                int     21h
                jc      quit    ;not found any more
                jmp     pr_0

quit:           cmp     dir_count,0
                jnz     quit1
                cmp     file_count,0
                jz      quit2
quit1:          mov     ax,file_count
                mov     di,offset directory_list
                xor     dx,dx
                call    print_dec
                mov     ax,dir_count
                mov     di,offset dir_count_str
                xor     dx,dx
                call    print_dec
                mov     ah,9
                mov     dx,offset directory_list
                int     21h

quit2:          mov     ah,4ch
		int	21h

p endp

;-----------------------------------------------------------
.286
;input  :       dx-high ax-low
;   cx  :       Max num of digit
;es:di  :       offset of last byte of digit
;output :       Output to string array
store_dec: 	pusha
		std
		xchg	bp,dx
		mov	si,10                 ;div by 10
		mov	bx,30h
store_dec1:     or      bp,bp
		jz	store_dec3
		xchg	bp,ax
		xor	dx,dx
		div	si
		xchg	bp,ax
		div	si
		or	dl,bl
		push	ax
		mov	al,dl
		stosb
		dec	cx
		pop	ax
		jmp	store_dec1

store_dec3:		xor	dx,dx
		div	si
		or	dl,bl
		push	ax
		mov	al,dl
		stosb
		dec	cx
		pop	ax
		or	ax,ax
		jnz	store_dec3
		jcxz	store_dec4
		mov	al,' '
		rep	stosb

store_dec4:	cld
		popa
		ret
;--------------------------------
;output DX:AX,dword (0-FFFFFFFFh / 0-4294967295)
print_dec:  
                xor cx,cx
                xchg bp,dx
                mov si,10 ;div by 10
                mov bx,30h
print_dec1:
                or bp,bp
                jz print_dec3
                xchg bp,ax
                xor dx,dx
                div si
                xchg bp,ax
                div si
                or dl,bl
                push dx
                inc cx
                jmp short print_dec1

print_dec3:     xor dx,dx
                div si
                or dl,bl
                push dx
                inc cx
                or ax,ax
                jnz print_dec3
print_dec4:
                pop ax
                stosb
                ;pop dx
                ;mov ah,2
                ;int 21h
                loop print_dec4
                ret
;-------------------------------

code ends
end p
